﻿using Admin.NET.Core;
using Furion.DependencyInjection;
using Furion.DynamicApiController;
using Mapster;
using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Mvc;
using MOKA.TPM.Application.Enum;
using MOKA.TPM.Application.Service;
using MOKA.TPM.Application.Service.Dto;
using MOKA.TPM.Entity;
using MOKA.TPM.Service.Dto;
using MOKA.TPM.Utility;
using MOKA.TPM.Utility.Const;
using SqlSugar;

namespace MOKA.TPM.Service;

/// <summary>
/// TPM非采出库业务逻辑控制器
/// </summary>
[ApiDescriptionSettings(TPMConst.GroupName, Name = "TPM_PartOut", Order = 305)]
[NonUnify]
public class PartOutService : TPMBaseService, IDynamicApiController, ITransient
{
    private readonly Service_Parts _partsService;
    private readonly Service_PartOutM _partOutMService;
    private readonly Service_PartOutD _partOutDService;
    private readonly Service_PartsStock _partsStockService;
    private readonly Service_PartsStockChange _partsStockChangeService;

    public PartOutService(UserManager userManager, IHttpContextAccessor accessor, ISqlSugarClient db, Service_PartOutM partOutMRep, Service_PartOutD partOutDRep, Service_PartsStock partsStockRep, Service_PartsStockChange partsStockChangeRep, Service_Parts partsRep, Service_SysDictDetail dicService)
                : base(userManager, dicService, accessor, db)
    {
        _partsService = partsRep;
        _partOutMService = partOutMRep;
        _partOutDService = partOutDRep;
        _partsStockService = partsStockRep;
        _partsStockChangeService = partsStockChangeRep;
    }

    /// <summary>
    /// 根据扫描的物料编码和车间获取物料库存信息
    /// </summary>
    /// <param name="obj"></param>
    /// <returns></returns>
    [ApiDescriptionSettings(Name = "GetPartNoStockInfo"), HttpPost]
    [AllowAnonymous]
    public async Task<CommonResult> GetPartNoStockInfoAsync(GetPartsStockInput obj)
    {
        CommonResult result = new CommonResult();

        try
        {
            PartsStock partsStockEntity = new PartsStock();

            string? PartNo = obj.PartNo;
            Guid? Workshop = obj.Workshop;
            var partsStockEntities = await _partsStockService.GetList(new GetPartsStockInput() { PartNo = PartNo, Workshop = Workshop });

            if (partsStockEntities != null && partsStockEntities.Count > 0)
            {
                result.Data = partsStockEntities;
                result.Result = true;
            }
        }
        catch (Exception ex)
        {
            result.Data = null;
            result.Result = false;
            result.Error = ex.Message.ToString();
        }
        return result;
    }

    /// <summary>
    /// 获取出库类型
    /// </summary>
    /// <returns></returns>
    [ApiDescriptionSettings(Name = "GetOutTypeData"), HttpPost]
    [AllowAnonymous]
    public async Task<CommonResult> GetOutTypeData()
    {
        CommonResult result = new CommonResult();
        try
        {
            var OutTypes = await _dicService.GetDetailListByDictCode("PartOutType", TPMDeviceGroupEnum.MROGroup);

            if (OutTypes != null && OutTypes.Count > 0)
            {
                result.Data = OutTypes;
                result.Result = true;
            }
        }
        catch (Exception ex)
        {
            result.Result = false;
            result.Error = ex.Message.ToString();
        }
        return result;
    }

    private async Task<string> GetOutBillNo()
    {
        string sql = " SELECT NEXT VALUE FOR MesTpm.dbo.PartOutBillNo  ";
        int num = await _db.AsTenant().GetConnectionScope(TPMConst.TPMConfigId).Ado.GetIntAsync(sql);
        return "O" + $"{num:D7}";
    }

    /// <summary>
    /// 提交出库
    /// </summary>
    /// <returns></returns>
    [ApiDescriptionSettings(Name = "DoOut"), HttpPost]
    [AllowAnonymous]
    public async Task<CommonResult> DoOutAsync(PartOutDto paraObj)
    {
        CommonResult result = new CommonResult();
        try
        {
            // JToken paraObj = JToken.Parse(paramJson);//如果传递的为字符串，则转化为JToken（JObject基类）
            LogHelper.Write("提交出库:", paraObj.ToString());

            if (paraObj.OutType == null || paraObj.OutType.ToString() == "")
            {
                throw new Exception("请指定出库类型!");
            }
            if (paraObj.Workshop == null || paraObj.Workshop.ToString() == "")
            {
                throw new Exception("请指定出库车间!");
            }
            if (paraObj.PartNo == null || paraObj.PartNo.ToString() == "")
            {
                throw new Exception("请指定物料信息!");
            }
            if (paraObj.Location == null || paraObj.Location.ToString() == "")
            {
                throw new Exception("请指定仓位!");
            }
            if (paraObj.OutNum == null || paraObj.OutNum.ToString() == "" || paraObj.OutNum < 0)
            {
                throw new Exception("请填写出库数量!");
            }
            if (paraObj.ToLine == null || paraObj.ToLine.ToString() == "")
            {
                throw new Exception("请指定生产线!");
            }

            //构建实体
            PartOutM thisOne = new PartOutM
            {
                Id = Guid.NewGuid(),
                BillNo = await GetOutBillNo(),
                OutType = paraObj.OutType.Value,
                OutStatus = (await _dicService.GetDetailByItemValue("PartOutStatus", "09", TPMDeviceGroupEnum.MROGroup)).Id,//自动标记为已确认
                Workshop = paraObj.Workshop.Value,
                OutTime = DateTime.Now,
                Remark = paraObj.Remark,
                CreateUser = paraObj.CreateUser,
                CreateTime = DateTime.Now,
                ConMan = paraObj.CreateUser,
                ConManName = paraObj.CreateUser,
                ConTime = DateTime.Now,
            };

            PartOutD partOutDEntity = new PartOutD
            {
                Id = Guid.NewGuid(),
                BillNo = thisOne.BillNo,
                PartNo = paraObj.PartNo,
                OutNum = paraObj.OutNum.Value,
                Location = paraObj.Location.Value,
                ToLine = paraObj.ToLine,
            };

            List<PartOutD> partOutDEntitys = new List<PartOutD>();

            if (await _partOutMService.GetOne(new PartOutMInput() { BillNo = thisOne.BillNo }) != null)//唯一索引
            {
                throw new Exception(String.Format("实体：{0}已存在！", thisOne.BillNo));
            }
            //启动事务
            using (var uow = _db.CreateContext())
            {
                if (await _partOutMService.AddData(thisOne.Adapt<AddPartOutMInput>()))
                {
                    partOutDEntity.Id = Guid.NewGuid();
                    partOutDEntity.BillNo = thisOne.BillNo;

                    partOutDEntitys.Add(partOutDEntity);

                    await _partOutDService.AddBulkData(partOutDEntitys);

                    //更新库存
                    decimal oldStock;

                    foreach (var item in partOutDEntitys)
                    {
                        var partStock = await _partsStockService.GetOne(new PartsStockInput() { PartNo = item.PartNo, Workshop = thisOne.Workshop, Location = item.Location });
                        oldStock = partStock.StockNum;
                        partStock.StockNum = partStock.StockNum - item.OutNum;//累减库存

                        if (partStock.StockNum < 0)
                        {
                            throw new Exception(string.Format("物料{0}出库失败,库存不足", item.PartNo));
                        }
                        await _partsStockService.UpdateData(partStock.Adapt<UpdatePartsStockInput>());

                        //插入库存历史表
                        PartsStockChange stockChangeEntity = new PartsStockChange();

                        stockChangeEntity.PartNo = item.PartNo;
                        stockChangeEntity.BillNo = thisOne.BillNo;
                        stockChangeEntity.ChgType = (await _dicService.GetDetailByItemValue("PartChgType", "02", TPMDeviceGroupEnum.MROGroup)).Id;
                        stockChangeEntity.Type = thisOne.OutType;
                        stockChangeEntity.Workshop = thisOne.Workshop;
                        stockChangeEntity.Location = item.Location;
                        stockChangeEntity.StoreQtyChanging = oldStock;
                        stockChangeEntity.Num = item.OutNum;
                        stockChangeEntity.StoreQtyChanged = oldStock - item.OutNum;
                        stockChangeEntity.ToLine = null;
                        stockChangeEntity.Remark = item.Remark;
                        stockChangeEntity.CreateUser = thisOne.CreateUser;
                        stockChangeEntity.CreateTime = thisOne.CreateTime;
                        stockChangeEntity.ConTime = thisOne.ConTime;
                        await _partsStockChangeService.AddData(stockChangeEntity.Adapt<AddPartsStockChangeInput>());
                    }
                }
                else
                {
                    throw new Exception("数据操作失败");
                }
                result.Data = thisOne.BillNo;//返回单号
                result.Result = true;
                //提交事务
                uow.Commit();
            }
        }
        catch (Exception ex)
        {
            result.Result = false;
            result.Error = ex.Message.ToString();
        }
        return result;
    }
}